﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using dtxCore;
using System.Runtime.InteropServices;


namespace dtxMinimize {
	public partial class frmMain : Form {

		private Config config;
		private List<DC_SavedProcesses> process_settings = new List<DC_SavedProcesses>();
		public delegate bool CallBackPtr(int hwnd, int lParam);
		private List<int> window_handles = new List<int>();
		private CallBackPtr callback;
		bool loading_programs = false;


		// Window Styles
		const UInt32 WS_OVERLAPPED = 0;
		const UInt32 WS_POPUP = 0x80000000;
		const UInt32 WS_CHILD = 0x40000000;
		const UInt32 WS_MINIMIZE = 0x20000000;
		const UInt32 WS_VISIBLE = 0x10000000;
		const UInt32 WS_DISABLED = 0x8000000;
		const UInt32 WS_CLIPSIBLINGS = 0x4000000;
		const UInt32 WS_CLIPCHILDREN = 0x2000000;
		const UInt32 WS_MAXIMIZE = 0x1000000;
		const UInt32 WS_CAPTION = 0xC00000;      // WS_BORDER or WS_DLGFRAME  
		const UInt32 WS_BORDER = 0x800000;
		const UInt32 WS_DLGFRAME = 0x400000;
		const UInt32 WS_VSCROLL = 0x200000;
		const UInt32 WS_HSCROLL = 0x100000;
		const UInt32 WS_SYSMENU = 0x80000;
		const UInt32 WS_THICKFRAME = 0x40000;
		const UInt32 WS_GROUP = 0x20000;
		const UInt32 WS_TABSTOP = 0x10000;
		const UInt32 WS_MINIMIZEBOX = 0x20000;
		const UInt32 WS_MAXIMIZEBOX = 0x10000;
		const UInt32 WS_TILED = WS_OVERLAPPED;
		const UInt32 WS_ICONIC = WS_MINIMIZE;
		const UInt32 WS_SIZEBOX = WS_THICKFRAME;

		// Extended Window Styles
		const UInt32 WS_EX_DLGMODALFRAME = 0x0001;
		const UInt32 WS_EX_NOPARENTNOTIFY = 0x0004;
		const UInt32 WS_EX_TOPMOST = 0x0008;
		const UInt32 WS_EX_ACCEPTFILES = 0x0010;
		const UInt32 WS_EX_TRANSPARENT = 0x0020;
		const UInt32 WS_EX_MDICHILD = 0x0040;
		const UInt32 WS_EX_TOOLWINDOW = 0x0080;
		const UInt32 WS_EX_WINDOWEDGE = 0x0100;
		const UInt32 WS_EX_CLIENTEDGE = 0x0200;
		const UInt32 WS_EX_CONTEXTHELP = 0x0400;
		const UInt32 WS_EX_RIGHT = 0x1000;
		const UInt32 WS_EX_LEFT = 0x0000;
		const UInt32 WS_EX_RTLREADING = 0x2000;
		const UInt32 WS_EX_LTRREADING = 0x0000;
		const UInt32 WS_EX_LEFTSCROLLBAR = 0x4000;
		const UInt32 WS_EX_RIGHTSCROLLBAR = 0x0000;
		const UInt32 WS_EX_CONTROLPARENT = 0x10000;
		const UInt32 WS_EX_STATICEDGE = 0x20000;
		const Int32 WS_EX_APPWINDOW = 0x40000; // This one
		const UInt32 WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
		const UInt32 WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
		const UInt32 WS_EX_LAYERED = 0x00080000;
		const UInt32 WS_EX_NOINHERITLAYOUT = 0x00100000; // Disable inheritence of mirroring by children
		const UInt32 WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring
		const UInt32 WS_EX_COMPOSITED = 0x02000000;
		const UInt32 WS_EX_NOACTIVATE = 0x08000000;


		/// <summary>
		/// Force another window to go into the state that it is requested to be in.
		/// </summary>
		/// <param name="windowHandle">Pointer to window to modify.</param>
		/// <param name="showState">State of the window to be placed in.</param>
		/// <returns>True on success; false on failure.</returns>
		[DllImport("user32.dll")]
		private static extern bool ShowWindow(IntPtr windowHandle, DC_WindowStates showState);

		[DllImport("user32.dll")]
		private static extern int EnumWindows(CallBackPtr callPtr, int lPar);

		[DllImport("user32.dll")]
		private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

		[DllImport("user32.dll", SetLastError = true)]
		static extern int GetWindowLong(IntPtr hWnd, int nIndex);

		[DllImport("user32.dll")]
		static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);


		public frmMain() {

			callback = new CallBackPtr(loadWindowsCallback);
			
			string settings_file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "dtxMinimize") + "\\settings.dcf";
			config = new Config(delegate(Config cfg){
				//No default settings needed.
			}, settings_file);

			DC_SavedProcesses[] loaded_processes = config.get<DC_SavedProcesses[]>("programs.settings");
			if (loaded_processes != null) {
				foreach (DC_SavedProcesses proc in loaded_processes) {
					process_settings.Add(proc);
				}
			}

			InitializeComponent();
		}

		private bool loadWindowsCallback(int hWnd, int lParam){
			uint process_id = 0;
			GetWindowThreadProcessId((IntPtr)hWnd, out process_id);

			Process proc = Process.GetProcessById((int)process_id);
			if (proc.MainWindowHandle != IntPtr.Zero && !window_handles.Contains(proc.MainWindowHandle.ToInt32())) {
				window_handles.Add(proc.MainWindowHandle.ToInt32());

				int new_row = _dgvProgramList.Rows.Add(Properties.Resources.circle_grey_16_ns,
					proc.ProcessName);
				_dgvProgramList.Rows[new_row].Tag = proc;

				Debug.WriteLine(proc.MainWindowHandle);
			}


			
			return true;
		}


		private void frmMain_Load(object sender, EventArgs e) {
			_dgvProgramList.ContextMenu = _contextMenu;
		}

		private void _btnRefresh_Click(object sender, EventArgs e) {
			loading_programs = true;
			
			_dgvProgramList.Rows.Clear();
			window_handles.Clear();
			// Do some pinvoking.
			EnumWindows(callback, 0);
			loading_programs = false;

			
		}

		private void groupBox1_Enter(object sender, EventArgs e) {

		}

		private void _dgvProgramList_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
			if(e.RowIndex != -1 && !loading_programs){
				DataGridViewRow row = _dgvProgramList.Rows[e.RowIndex];
				Process proc = row.Tag as Process;
				NotifyIcon icon;

				switch((string)row.Cells[2].Value){
					case "Show In Tray Only":
						int test = GetWindowLong(proc.MainWindowHandle, -20) |~WS_EX_APPWINDOW;
						SetWindowLong(proc.MainWindowHandle, -20, test);
						//ShowWindow(proc.MainWindowHandle, DC_WindowStates.Hide);
						//ShowWindow(proc.MainWindowHandle, DC_WindowStates.Restore);
						icon = new NotifyIcon();
						icon.Icon = Icon.ExtractAssociatedIcon(proc.MainModule.FileName);
						icon.Visible = true;
						break;

					case "Show In Taskbar Only":
						
						break;

					case "Taskbar & Tray":
						ShowWindow(proc.MainWindowHandle, DC_WindowStates.ShowDefault);
						icon = new NotifyIcon();
						icon.Icon = Icon.ExtractAssociatedIcon(proc.MainModule.FileName);
						icon.Visible = true;
						break;

				}
				
			}

		}
	}

}
